<script setup>
import {computed, nextTick, ref} from 'vue'
import {RemoveFilled} from '@element-plus/icons-vue'
import {chatService, chatStreamService, openAiImageService, openAiTTSService} from "@/api/chatgpt.js";
import {useChatGptStore} from "@/stores/chatStore.js";

const options = [
    {
        value: 'gpt-3.5-turbo',
        label: 'chatgpt-3.5-turbo'
    },
    {
        value: 'gpt-3.5-turbo-16k',
        label: 'chatgpt-3.5-turbo-16k'
    },
    {
        value: 'dall-e-3',
        label: 'openai-dall-e-3'
    },
    {
        value: 'gpt-4-turbo',
        label: 'chatgpt-4'
    },
    {
        value: 'gpt-4-32k',
        label: 'chatgpt-4-32k'
    },
    {
        value: 'tts-1',
        label: 'TTS'
    }
]
const value = ref('gpt-3.5-turbo')
const textarea = ref('')
const isButtonDisabled = computed(() => {
    return textarea.value.trim() === ''
})
const sc_height = ref('600px')
window.onresize = function () {
    sc_height.value = (window.innerHeight - 310) + 'px'
}
sc_height.value = (window.innerHeight - 310) + 'px'
const UMessages = ref([])

const chatStore = useChatGptStore()
UMessages.value = chatStore.chats
const UserMessage = ref({
    type: 'user',
    data: ''
})
let source = null
const addMessageToSend = async (Message) => {
    const newMessage = {...UserMessage.value, data: Message}
    UMessages.value.push(newMessage)
    if (value.value === 'dall-e-3') {
        const Image = await openAiImageService(Message)
        const newGptMessage = ref({...gptMessage.value, data: Image.data})
        UMessages.value.push(newGptMessage.value)
        isView.value = false
    } else if (value.value === 'tts-1') {
        const audio = await openAiTTSService(Message)
        const newGptMessage = ref({...gptMessage.value, data: audio.data})
        UMessages.value.push(newGptMessage.value)
        isView.value = false
    } else {
        const FluxUrl = await chatStreamService()
        const params = new URLSearchParams();
        params.append("message", Message)
        params.append("model", value.value)
        const eventsourceUrl = `${FluxUrl.data}?${params.toString()}`
        source = new EventSource(eventsourceUrl)
        let counter = 0
        const newGptMessage = ref({...gptResponseMessage.value, data: []})
        UMessages.value.push(newGptMessage.value)
        source.onmessage = (event) => {
            const data = event.data
            const Jdata = JSON.parse(data)
            if (Jdata.result.output.content === null || Jdata.result.output.content === '') {
                counter++;
            }
            if (counter >= 2) {
                chatStore.setChats(UMessages.value)
                source.close()
                isView.value = false
            }
            console.log(Jdata)
            newGptMessage.value.data.push(Jdata.result.output.content)
        }
    }
}
const clearTextArea = () => {
    textarea.value = ''
}
const gptMessage = ref({
    type: 'assistant',
    data: ''
})
const gptResponseMessage = ref({
    type: 'assistantResponse',
    data: []
})
const loading = ref(false)
const whoAreChatGPT = async () => {
    const response = await chatService(value.value)
    gptMessage.value.data = response.data
    UMessages.value.push(gptMessage.value)
    loading.value = false
    chatStore.setChats(UMessages.value)
}
if (UMessages.value.length === 0) {
    whoAreChatGPT()
} else {
    loading.value = false
}
const isImage = (str) => {
    const regex = /^https?:\/\/.*/;

    // 使用正则表达式测试 URL
    return regex.test(str);
}

const innerRef = ref()
const scrollbarRef = ref()

const downScrollbar = () => {
    nextTick(() => {
        scrollbarRef.value.setScrollTop(innerRef.value.clientHeight);
    })
}

const svg = `
        <path class="path" d="
          M 30 15
          L 28 17
          M 25.61 25.61
          A 15 15, 0, 0, 1, 15 30
          A 15 15, 0, 1, 1, 27.99 7.5
          L 15 15
        " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
      `
const isView = ref(false)
const showButton = () => {
    isView.value = true
}
const stopResponse = () => {
    source.close()
    isView.value = false
}

const isBase64Audio = (data) => {
    try {
        const decodeData = atob(data)
        const audioBlob = new Blob([decodeData], {type: 'audio/mpeg'})
        const audioUrl = URL.createObjectURL(audioBlob)
        console.log(audioUrl)
        const audioElement = new Audio(audioUrl)
        return true
    } catch (e) {
        return false
    }
}
const getAudioURL = (data) => {
    const decodeData = atob(data);
    const audioBlob = new Blob([decodeData], {type: 'audio/mpeg'})
    return URL.createObjectURL(audioBlob)
}
</script>

<template>
    <div style="width: 100%">
        <el-row>
            <el-col :lg="6" :md="8" :sm="12" :xl="3" :xs="24">
                <el-select v-model="value" placeholder="chatgpt-3.5-turbo" style="width: 60%">
                    <el-option v-for="item in options" :key="item.value" :disabled="item.disabled" :label="item.label"
                               :value="item.value"/>
                </el-select>
            </el-col>
        </el-row>
        <div class="custom-row2">
            <el-row justify="start">
                <el-col :lg="14" :md="14" :offset="6" :sm="14" :xl="10" :xs="14">
                    <el-scrollbar ref="scrollbarRef" v-loading="loading" :element-loading-spinner="svg"
                                  :height="sc_height"
                                  :max-height="sc_height"
                                  element-loading-svg-view-box="-10,-10,50,50"
                                  element-loading-text="加载中... 遇到错误请刷新"
                    >
                        <div ref="innerRef">
                            <div class="status">
                                <img class="status-icon" src="/src/assets/chatGPT.svg">
                                <span class="status-text">ChatGPT是一种基于生成式预训练模型的聊天机器人，它通过学习大量的文本数据来生成自然语言响应。它是由OpenAI开发的，建立在GPT（Generative Pre-trained Transformer）模型的基础上。ChatGPT可以用于多种应用，包括智能助手、在线客服、聊天机器人等。它可以接收用户的文本输入，并生成相应的回复。ChatGPT的优势在于其能够产生连贯、有逻辑性的语言响应，能够理解上下文和处理复杂的对话</span>
                            </div>
                            <div class="chat-item">
                                <div v-for="(message, index) in UMessages" :key="index" :class="message.type"
                                     class="chat-item">
                                    <img :src="message.type === 'user' ? '/src/assets/avatar.png' : '/src/assets/chatGPT.svg'"
                                         width="55px">
                                    <span v-if="message.type === 'user'" class="user">我：</span>
                                    <span v-else class="assistant">GPT：</span><br><br>
                                    <div class="chatBg">
                    <span v-if="isBase64Audio(message.data)" class="audio">
                      <audio controls><source :src="getAudioURL(message.data)" type="audio/mp3"></audio>
                    </span>
                                        <el-image v-else-if="isImage(message.data)" :hide-on-click-modal="true"
                                                  :initial-index="0" :preview-src-list="[message.data]"
                                                  :src="message.data"
                                                  fit="fill" z-index="99999"/>
                                        <span v-for="(char,index) in message.data"
                                              v-else-if="message.type === 'assistantResponse'" :key="index">
                    {{ char }}
                  </span>
                                        <span v-else>
                    {{ message.data }}
                  </span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </el-scrollbar>
                </el-col>
            </el-row>

            <el-row class="el-row-input" justify="start">
                <el-col :lg="18" :md="18" :offset="7" :sm="18" :xl="14" :xs="18">
                    <img height="80px" src="/src/assets/chatGPT.svg" width="80px"> 开发中
                </el-col>
                <el-col :lg="18" :md="18" :offset="7" :sm="18" :xl="14" :xs="18">
                    <div class="stopButton">
                        <el-button v-if="isView" plain type="danger" @click="stopResponse()">
                            <el-icon>
                                <RemoveFilled/>
                            </el-icon>
                            停止
                        </el-button>
                    </div>
                    <el-input
                            v-model="textarea"
                            maxlength="4000"
                            placeholder="与chatgpt交谈"
                            show-word-limit
                            style="width: 82%"
                            type="textarea"
                    ></el-input>
                    <el-button :disabled="isButtonDisabled"
                               type="primary"
                               @click="addMessageToSend(textarea);downScrollbar();clearTextArea();showButton()">
                        <img src="/src/assets/dark_main_logo.svg" width="20px">
                        提交
                    </el-button>
                </el-col>
            </el-row>
        </div>

    </div>

</template>

<style lang="scss">
.el-row-input {
  margin-bottom: 25px;
  display: flex;
  flex-wrap: wrap;
  position: absolute;
  bottom: 0;
  left: 190px;
  z-index: 7000;
  //background-color: #fff;
  width: 80%;
}

.chat-log {
  display: flex;
  flex-direction: column;
}

.chat-item {
  padding: 10px;
  margin-bottom: 10px;
  white-space: pre-wrap;
}

.user {
  align-self: flex-start;
}

.assistant {
  align-self: flex-end;
}

.status {
  display: flex;
  align-items: center;
  background: linear-gradient(45deg, rgba(255, 0, 255, 0.5), rgba(0, 255, 255, 0.5));
  border-radius: 70px;
}

.status-icon {
  margin-right: 10px;
}

.status-text {
  font-size: 16px;
  font-weight: bold;
}

.chatBg {
  background: linear-gradient(45deg, rgba(255, 0, 255, 0.07), rgba(0, 255, 255, 0.07));
  border-radius: 10px;
}

.stopButton {
  display: flex;
  flex-direction: row;
  justify-content: center;
  margin-right: 135px; /* 向右移动 20 像素 */
}
</style>